﻿<template>
    <el-form
        ref="elForm"
        :model="formData"
        :rules="rules"
        :label-width="cfg.label_width"
        :label-position="cfg.label_position"
        :disabled="false"
    >
        <template v-for="item in formItems" :key="item">
            <my-form-row :tb="tb" :row="item" :formData="formData" :computeData="computeData"></my-form-row>
        </template>
        <el-form-item v-if="cfg.actions && cfg.actions.length>0">
           <div style="display:flex;width: 100%;">
                <!--自定义功能按钮-->
                <template v-for="btn in cfg.actions" :key="btn.label">
                    <div style="flex:1" v-if="!btn.label"></div>
                    <el-button 
                        :type="btn.type"
                        v-else-if="btn.label && checkIf(btn.vif)"
                        @click="doClick(btn.click)"
                    >{{ btn.label }}</el-button>
                </template>
            </div>
        </el-form-item>
    </el-form>
</template>

<script>
import { computed } from "vue";
import { Utils } from "./main";
import mydate from './mydate.js';

export default {
    name: "MyFormPage",
    props: {
        tbname: {
            type: String,
            required: true,
        },
        formName: {
            type: String,
            default: "form",
        },
        allowDelete: {
            type: Boolean,
            default: true
        },
        pk:[String,Number]
    },
    provide() {
        return {
            MyPage: this,
        };
    },
    emits: ["added", "updated", "deleted", "close"],
    data() {
        return {
            state: {
                dlgVisible: false,
                readonly: false,
                cform_com: String,
                cform_cfg: Object,
            },
            cfg: {
                title: "",
                width: "800px",
                label_position: "right",
                label_width: "80px",
                actions: [],
                items: [],
            },
            formData: {
                ID: 0,
            },
            oldFormData: {},
            rules: {},
            //动态增加的计算字段
            computeData: {},
        };
    },
    created() {
        this.initByTbName(this.tbname);
        if(this.pk){
            this.open(this.pk);
        }
    },
    methods: {
        call(action, pm){
            if(action.indexOf("/")!=-1){
                return $server.call(action, pm, this.$el);
            }
            return $server.doAction(this.tbname, pm, this.$el);
        },
        initByTbName(_tbname) {
            if (!_tbname) return;
            this.$server.getDM(_tbname).then((tb) => {
                this.rules = tb.rules || {};
                for (let key in this.rules) {
                    this.rules[key].myform = this;
                }

                this.tb = tb;
                var cfg = tb[this.formName];
                if(cfg.columns){
                    tb.columns = cfg.columns;
                }

                if (this.$mbh5) {
                    if (cfg.label_position2) {
                        cfg.label_position = cfg.label_position2;
                    } else {
                        cfg.label_position = "top";
                        cfg.width = "100%";
                    }
                }

                if (typeof cfg.actions != "object") {
                    cfg.actions = [];
                }

                cfg.title = tb.title;
                this.cfg = cfg;
                //处理form扩展
                this.proceformExtend();
                this.setDefaultValue();

                if (this.cfg.vue && this.cfg.vue.created) {
                    this.doClick(this.cfg.vue.created);
                }
            });
        },
        view(id, item) {
            this.open(id, item);
            this.state.readonly = true;
        },
        setDefaultValue() {
            //设置默认值
            if (this.tb) {
                //上级list页面的搜索条件，form页面中取默认值可能会用到
                let psearch = (this.$parent && this.$parent.search) ? this.$parent.search : {};

                for (var ix = 0; ix < this.tb.columns.length; ix++) {
                    var col = this.tb.columns[ix];
                    if (col.default != undefined) {
                        this.formData[col.code] = mydate.getDefaultValue(col.default, psearch);
                    } else {
                        if (col.type == "int" || col.type == "number") {
                            if (col.control == "select" || col.control == "selectinput") {
                                //this.formData[col.code] = "";
                            } else {
                                this.formData[col.code] = 0;
                            }

                        } else if (col.type == "string") {
                            this.formData[col.code] = "";
                        }
                    }
                }
            }
            this.oldFormData = { ...this.formData };
        },

        open(id, item) {
            if (typeof this.onBeforeOpen == "function") {
                this.onBeforeOpen();
            }
            this.state.readonly = false;
            this.formData = { ID: 0 };
            this.oldFormData = { ID: 0 };
            if (this.$refs.elForm) {
                try {
                    this.$refs.elForm.resetFields();
                    this.$refs.elForm.clearValidate();
                } catch (e) {
                    console.log(e);
                }
            }
            this.setDefaultValue();

            if (typeof (id) == "object") {
                item = id;
            }

            this._id_ = id;
            if (!item) {
                this.loadData();
            } else {
                if (typeof item == "object") {
                    //this.formData里面有初始默认值
                    this.formData = { ...this.formData, ...item };
                } else if (typeof id == "object") {
                    this.formData = id;
                }
                if (id > 0 && typeof this.onAfterOpen == "function") {
                    this.onAfterOpen(id, this.formData);
                }
            }
            if (id == 0) {
                if (typeof this.onCreated == "function") {
                    this.onCreated();
                }
                if (typeof this.onAfterOpen == "function") {
                    this.onAfterOpen(0, this.formData);
                }
            }

            this.oldFormData = { ...this.formData };
            this.state.dlgVisible = true;
        },

        loadData() {
            let test = (typeof this._id_ == "number" && this._id_ > 0) || (typeof this._id_ == "string" && this._id_ != "");
            if (test) {
                var el = this.$refs.elForm ? this.$refs.elForm.$el : null;
                this._loading = true;
                this.$server.get(this.tbname, this._id_, el).then((res) => {
                    if (typeof this.checkViewRight == "function") {
                        if(!this.checkViewRight(res)){
                            $msg.alert("无权查看");
                            this.close();
                            return;
                        }
                    }
                    
                    if (typeof this.onAfterLoadData == "function") {
                        this.onAfterLoadData(res);
                    }
                    if (typeof this.onAfterOpen == "function") {
                        this.onAfterOpen(this._id_, res);
                    }
                    this.oldFormData = { ...res };
                    this.formData = res;
                }).finally(() => {
                    var me = this;
                    setTimeout(() => {
                        me._loading = false;
                    }, 300);
                })
            }
        },
        close(updated) {
            this.state.dlgVisible = false;
            if (updated) {
                //关闭收通知父组件，需要刷新数据
                this.$emit("updated");
            }
            this.$emit("close");
        },
        doDelete() {
            if (typeof this._id_ == "object") {
                this.$emit("deleted", this._id_);
                return;
            }
            this.$server.delete(this.tbname, this.formData.ID).then(() => {
                $msg.message("操作成功");
                this.$emit("deleted", this.formData);
                this.close();
            });
        },
        hasChange() {
            let s1 = JSON.stringify(this.formData);
            let s2 = JSON.stringify(this.oldFormData);
            return s1 != s2;
        },

        validate(showError) {
            if (!showError) {
                return this.$refs.elForm.validate();
            }
            return new Promise((resolve, reject) => {
                var me = this;
                this.$refs.elForm.validate(function (isOK, errs) {
                    if (!isOK && showError) {
                        var msgs = [];
                        Object.keys(errs).forEach(key => {
                            var items = errs[key];
                            if (items.forEach) {
                                items.forEach(item => {
                                    msgs.push(item.message);
                                })
                            }
                        })
                        $msg.error(msgs.join("<br />"));
                    } else {
                        resolve(isOK, errs);
                    }
                });
            });
        },
        doSave() {
            //是否保存完成以后，关闭
            var me = this;
            this.$refs.elForm.validate(function (isOK, errs) {
                if (isOK) {
                    me._innerSave();
                    return;
                }
                var msgs = [];
                Object.keys(errs).forEach(key => {
                    var items = errs[key];
                    if (items.forEach) {
                        items.forEach(item => {
                            msgs.push(item.message);
                        })
                    }
                })
                $msg.error(msgs.join("<br />"));
            });

            // if(!this.hasChange()){
            //     $msg.alert("数据没有变化，无需保存");
            //     return;
            // }

        },
        _innerSave() {
            if (typeof this.onBeforeUpdate == "function") {
                var checkMessage = this.onBeforeUpdate(this.formData);
                if (checkMessage) {
                    $msg.alert(checkMessage);
                    return;
                }
            }
            if (typeof this._id_ == "object") {
                if (this.formData.ID == 0) {
                    this.$emit("added", this.formData);
                } else {
                    this.$emit("updated", this.formData);
                }
                return;
            }
            this.$server.update(this.tbname, this.formData).then(res => {
                let newID = 0;
                if (res.startsWith("OK:")) {
                    newID = res.substring(3);
                    if (parseInt(newID) == newID) {
                        newID = parseInt(newID);
                    }
                }
                try {
                    if (this.formData.ID == 0) {
                        this._id_ = newID;
                        this.formData.ID = newID;
                        this.$emit("added", this.formData);
                    } else {
                        this.$emit("updated", this.formData);
                    }
                } catch (e) {
                    console.log(e);
                }
                this.loadData();
                $msg.message("操作成功");
            });
        },
        checkIf(vif) {
            if (typeof vif == "function") {
                return vif.apply(this);
            } else if (typeof vif == "string") {
                return this.computeData[vif] != false;
            }
            return true;
        },
        doClick(func) {
            Utils.doFunc(func, this);
        },
        proceformExtend() {
            if (this.tb.ext) {
                //通用扩展+form专用扩展
                if (this.tb.ext.common) {
                    let ext = this.tb.ext.common;
                    //动态添加watch
                    this.proceFormWatch(ext.watch);
                    //动态添加计算属性
                    this.proceFormComputed(ext.computed);
                    //添加动态method
                    this.proceFormMethods(ext.methods);
                }

                if (this.tb.ext.form) {
                    let ext = this.tb.ext.form;
                    //动态添加watch
                    this.proceFormWatch(ext.watch);
                    //动态添加计算属性
                    this.proceFormComputed(ext.computed);
                    //添加动态method
                    this.proceFormMethods(ext.methods);
                }
            }
            if (this.cfg.vue) {
                //动态添加watch
                this.proceFormWatch(this.cfg.vue.watch);
                //动态添加计算属性
                this.proceFormComputed(this.cfg.vue.computed);
                //添加动态method
                this.proceFormMethods(this.cfg.vue.methods);
            }
        },
        proceFormWatch(w) {
            for (let key in w) {
                let val = w[key];
                if (typeof val == "function") {
                    this.$watch(key, (newVal, oldVal) => {
                        try {
                            val.apply(this, [newVal, oldVal]);
                        } catch (e) {
                            alert("自定义watch执行错误:" + e);
                        }
                    },
                        { deep: true });
                }
            }
        },
        proceFormComputed(c) {
            for (let key in c) {
                let cfield = c[key];
                if (typeof cfield == "function") {
                    this.computeData[key] = computed(() => cfield.apply(this));
                } else if (typeof cfield.get == "function") {
                    this.computeData[key] = computed({
                        get: () => {
                            try {
                                return cfield.get.apply(this);
                            } catch (e) {
                                console.log("计算字段取值出错：" + key);
                            }
                        },
                        set: (newValue) => {
                            try {
                                cfield.set.apply(this, [newValue]);
                            } catch (e) {
                                console.log(
                                    "计算字段Set出错：" + key + "," + newValue
                                );
                            }
                        },
                    });
                }
            }
        },
        proceFormMethods(m) {
            for (let key in m) {
                let func = m[key];
                if (typeof func == "function") {
                    this[key] = func.bind(this);
                } else {
                    console.log("method定义错误：" + key);
                }
            }
        },
    },
    computed: {
        allowDelete2() {
            if ("allowDelete" in this.computeData) {
                return this.computeData["allowDelete"];
            }
            //手机版页面才有删除按钮
            return (
                this.$mbh5 &&
                this.allowDelete &&
                !this.state.readonly &&
                this.cfg.actions.length == 0 &&
                (this.formData.ID > 0 || this.formData.ID != "")
            );
        },
        allowSave() {
            if ("allowSave" in this.computeData) {
                return this.computeData["allowSave"];
            }
            return !this.state.readonly && this.cfg.actions.length == 0;
        },
        formItems() {
            let items = null;
            if (this.$mbh5) {
                items = this.cfg["items_wx"];
            }

            return items || this.cfg.items;
        },

    },
    watch: {
        tbname(val) {
            this.initByTbName(val);
        },
        pk(val){
            if(val){
                this.open(val);
            }else{
                this.setDefaultValue();
            }
        }
    }
};
</script>

<style scoped>
.el-button {
    padding: 4px 8px;
}
.el-button + .el-button {
    margin-left: 6px;
}
</style>